﻿#ifndef _TECH_STRATEGY_H_
#define _TECH_STRATEGY_H_
//#include "../FacilityBaseLib/DateTime.hpp"
#include "TechParameter.h"
#include "../FacilityBaseLib/plate.h"
#include "../FacilityBaseLib/InstrumentInfo.h"
#include <vector>
#include <string>
#include <list>
using namespace std;

/////////////////////////////////////////////////////////////////////////////
// CRateParam
/***	
	//期货没有费税;
*/
class TECH_API CRateParam
{
public:
	CRateParam( );

    bool	IsValid( );
	void	SetDefault( );
	//void	Serialize( CArchive &ar );

	double	GetRate( InstrumentInfo & info );

	double	m_dShaa;
	double	m_dShab;
	double	m_dShafund;
	double	m_dSzna;
	double	m_dSznb;
	double	m_dSznfund;
};

/////////////////////////////////////////////////////////////////////////////
// CSPTimeContainer

//template class __declspec(dllexport)	CSPArray<CSPTime, CSPTime &>;
//typedef	std::vector<DateTime>	CSPTimeArray;

// class	TECH_API CSPTimeContainer : public CSPTimeArray
// {
// public:
// 	CSPTimeContainer() {}
// 	virtual ~CSPTimeContainer()	
// 	{	
// 		RemoveAll();	
// 	}
// 	// for access CSPTimeArray
// 	virtual	int		Add( DateTime tm )
// 	{
// 		CSPTimeArray::push_back( tm );
// 		return size()-1;	
// 	}
// 	virtual	void	RemoveAll( )
// 	{	
// 		CSPTimeArray::clear();	
// 	}
// 	DateTime ElementAt(int idx)
// 	{
// 		return (*this)[idx];
// 	}
// };

/////////////////////////////////////////////////////////////////////////////
// COpParam

TECH_API string	AfxGetLogicString( int nLogic );

TECH_API string	AfxGetStoreDivString( int nStoreDiv );

/***
	策略模拟操作条件类;
*/
class TECH_API COpParam
{
public:
	COpParam( );

	// Attributes
	bool	IsValid( );
	void	SetDefault( );
	void	SetDefaultOfInvalidMember( );
//	void	Serialize( CArchive &ar );

	// Operation
	bool	IsInTimeZones(time_t tm);
	time_t	GetBeginTime( );
	time_t	GetEndTime();
	bool	GetNextTradeTime(time_t tmNow, time_t &tmNext);
	DWORD	GetProgress(time_t tmNow, DWORD dwProgressMax);

	enum storeDivs {
		storedivMin		=	0x01,
		storedivOnce	=	0x01,
		storedivTwice	=	0x02,
		storedivThird	=	0x03,
		storedivForth	=	0x04,
		storedivFifth	=	0x05,
		storedivSixth	=	0x06,
		storedivSeventh	=	0x07,
		storedivEighth	=	0x08,
		storedivNinth	=	0x09,
		storedivTenth	=	0x0A,
		storedivMax		=	0x0A,
	};

	enum Logical {
		logicMin	=	0x01,
		logicAnd	=	0x01,
		logicOr		=	0x02,
		logicMax	=	0x02,
	};

	int		m_nKType;
	int		m_nMaindataType;
	int		m_nBuyLogic;
	int		m_nBuyLimit;
	double	m_dBuyMulti;
	int		m_nSellLogic;
	int		m_nSellLimit;
	double	m_dSellMulti;
	std::vector<time_t>	m_atmBegin;
	std::vector<time_t>	m_atmEnd;
	long	m_nStartAmount;		//	元
	int		m_nStoreDiv;

	bool	m_bStopLosing;
	bool	m_bStopProfit;
	double	m_dStopLosing;
	double	m_dStopProfit;
	bool	m_bLongTrend;
	bool	m_bIndexTrend;
	int		m_nKTypeLong;
	int		m_nKTypeIndex;
};

/////////////////////////////////////////////////////////////////////////////
// stockown_t

#pragma pack(1)

typedef	struct instrumentown_t	{
	char	szCode[31];
	char	direct;
	DWORD	dwShare;
	double	dBuyPrice;
	char	szMarket[9];
	char	szReserved[20];
} INSTRUMENTOWN, * LPINSTRUMENTOWN;

//template class __declspec(dllexport)	CSPArray< STOCKOWN, STOCKOWN & >;
typedef	vector< INSTRUMENTOWN>	CInstrumentOwnArray;

/***
	拥有合约数组;
*/
class TECH_API CInstrumentOwnContainer : public CInstrumentOwnArray
{
public:
	virtual ~CInstrumentOwnContainer()	{	RemoveAll();	}

	// for access CStockOwnArray
	virtual	void	RemoveAll( )			{	clear();	}

	bool	AddInstruemnt( InstrumentInfo & info, DWORD dwShare, double dBuyPrice );
	bool	RemoveInstrument(InstrumentInfo & info, DWORD dwShare);
	bool	HasThisInstrument(InstrumentInfo & info, LPINSTRUMENTOWN lpOwn);
	INSTRUMENTOWN ElementAt(int idx){return (*this)[idx];}
	int GetSize(){return size();}

};

/////////////////////////////////////////////////////////////////////////////
// oprecord_t

// 操作类型
#define	STRATEGY_OPTYPE_BUY			0x01	// 买入
#define	STRATEGY_OPTYPE_SELL		0x02	// 卖出
#define	STRATEGY_OPTYPE_ADDSTOCK	0x03	// 添加合约
#define	STRATEGY_OPTYPE_REMOVESTOCK	0x04	// 移除合约
#define	STRATEGY_OPTYPE_ADDCASH		0x05	// 添加资金
#define	STRATEGY_OPTYPE_REMOVECASH	0x06	// 取走资金

string	AfxGetStrategyOpTypeString( long lOpType );

typedef	struct oprecord_t	{
	long	lOpType;
	time_t	time;
	char	szCode[31];
	DWORD	dwShare;
	double	dSharePrice;
	double	dRateCost;
	long	bViewed;	// for next op use in realop. 
	char	dwMarket[9];
	char	szReserved[24];
} OPRECORD, * LPOPRECORD;

//template class __declspec(dllexport)	CSPArray< OPRECORD, OPRECORD & >;
typedef	vector< OPRECORD>	COpRecordArray;
/***
	操作记录数组;
*/
class COpRecordContainer : public COpRecordArray
{
public:
	virtual ~COpRecordContainer()	{	RemoveAll();	}

	// for access COpRecordArray
	virtual	int		Add( OPRECORD &newElement){	COpRecordArray::push_back(newElement);return size()-1;	}
	virtual	void	RemoveAt(int nIndex, int nCount = 1){	COpRecordArray::erase(begin()+nIndex,begin()+nIndex+nCount);	}
	virtual	void	RemoveAll( )			{	COpRecordArray::clear();	}
	virtual	void	Copy(const COpRecordArray& src)	{ copy(src.begin(),src.end(),this->begin());	}

	// operation
	int		AddRecord(	long lOpType, time_t tm, const char *szCode,
						DWORD dwShare, double dSharePrice, double dRateCost );
	int		AddRecordUniqueStock(long lOpType, time_t tm, const char *szCode,
					   DWORD dwShare, double dSharePrice, double dRateCost );
	int		GetBuyRecordCount();
    bool	HasBuyStock( const char * szCode );
    bool	StatResults( int *pnTimes, int *pnVictoryTimes, double *pdYieldMax, double *pdYieldMin );
	OPRECORD& ElementAt(int idx){return (*this)[idx];}
	DWORD GetSize(){return size();}
};

typedef	struct assetserial_t{
	time_t	time;
	double	dAsset;
	double	dCash;
	char	szReserved[32];
} ASSETSERIAL , * LPASSETSERIAL;

inline bool operator ==(const ASSETSERIAL& asset1,const ASSETSERIAL& asset2)
{
	return asset1.time==asset2.time;
}
inline bool operator <(const ASSETSERIAL& asset1,const ASSETSERIAL& asset2)
{
	return asset1.time<asset2.time;
}


typedef	std::list< ASSETSERIAL>	CAssetSerialArray;
/***
	资产数组;
*/
class TECH_API CAssetSerialContainer : public CAssetSerialArray
{
public:
	virtual	~CAssetSerialContainer()	{	RemoveAll();	}

	// for access CAssetSerialArray
	virtual	void	RemoveAt(int nIndex, int nCount = 1){
		CAssetSerialArray::iterator iter=begin();
		for (int i=0;i<nIndex;i++)
		{
			++iter;
			if (iter==end())
			{
				return ;
			}
		}
		for (int j=0;j<nCount;j++)
		{
			if (iter!=end())
			{
				iter=this->erase(iter);
			}
			iter++;
		}

		//CAssetSerialArray::erase(begin()+nIndex,begin()+nIndex+nCount);	
	}
	virtual	void	RemoveAll( )			{	CAssetSerialArray::clear();	}
	virtual	void	Copy(const CAssetSerialArray& src)	{	
		copy(src.begin(),src.end(),this->begin());
	}

	// operation
	bool	SortInsert( ASSETSERIAL serial );
	bool	GetStdDev( double *pdStdDev, double * pdXiapu );
	ASSETSERIAL ElementAt(int idx){
		CAssetSerialArray::iterator iter=begin();
		for (int i=0;i<idx;i++)
		{
			
			if (iter==end())
			{
				break;
			}
			++iter;
		}
		if (iter!=end())
		{
			return *iter;
		}
		return ASSETSERIAL();
	}
	DWORD GetSize(){return size();}
};

#pragma pack()

//////////////////////////////////////////////////////////////////////
// CTechInstrument
/***
	待操作的合约，包含合约信息，K线数据，所需技术指标
*/
class TECH_API CTechInstrument
{
public:
	CTechInstrument();
	CTechInstrument( const CTechInstrument & src );
	virtual	~CTechInstrument();

	CTechInstrument	& operator = ( const CTechInstrument &src );
    void	SetAutoDelete( bool bAutoDelete = true );
	void	Clear();

    bool	GetPriceOK( long lOpType, time_t tmCur, DWORD dwShare, double dSharePrice, double *pdPriceOK );
    bool	IsStopTrading( time_t tmCur );
	bool	GetClosePrice(time_t tmCur, double *pdPrice);
	bool	GetCloseDiffPercent(time_t tmCur, double *pdDiffPercent);

	InstrumentInfo	m_info;		// 合约信息
	KdataContainer			m_kdata;		// 所需K线数据
	KdataContainer			m_kdataLong;	// 长周期K线数据
	std::vector<void*>		m_techs;		// 所需技术指标
	std::vector<void*>		m_techsLong;	// 所需长周期技术指标

protected:
	bool	m_bAutoDelete;
};

//template class __declspec(dllexport)	CSPArray< CTechInstrument, CTechInstrument & >;
typedef	vector< CTechInstrument>	CTechIstrumentArray;
/***
	CTechInstrument数组
*/
class TECH_API CTechInstrumentContainer : public CTechIstrumentArray
{
public:
	virtual	~CTechInstrumentContainer( );

	// for access CTechStockArray
	virtual	void SetSize(int nNewSize, int nGrowBy = -1)	{	CTechIstrumentArray::resize(nNewSize);	}

	// operation
	void	Clear( );
	
	// Operation
	bool	GetShouldBuyShare(CTechInstrument & techstock, time_t tmCur, double dCash, CRateParam &rate, COpParam &opparam, int nOwnedStockCount,
		time_t *ptmOp, DWORD *pdwShare, double *pdSharePrice);
	bool	GetShouldSellShare(	CTechInstrument & techstock, time_t tmCur, INSTRUMENTOWN &own, COpParam &opparam,
		time_t *ptmOp, DWORD *pdwShare, double *pdSharePrice);

	bool	GetClosePrice(const char * szCode, time_t tmCur, double * pdPrice);
	bool	GetSumAsset( time_t tmCur, CInstrumentOwnContainer &container, double * pdAsset );
	bool	GetNextExistTradeTime(time_t tmCur, time_t & tmNext);

	KdataContainer		m_infoIndex;
	KdataContainer			m_kdataIndex;
	vector<void* >		m_techsIndex;
	CTechInstrument ElementAt(int idx){return (*this)[idx];}
};

/////////////////////////////////////////////////////////////////////////////
// CStrategy
#ifndef _WIN32
#define CALLBACK
#endif
typedef bool ( CALLBACK* SIMULATION_CALLBACK)(DWORD dwType, DWORD dwValue, const char* lpszMsg, void * cookie);

#define	STRATEGY_MAX_TITLE			256

#define	SIMULATION_PROGRESS			1
#define	SIMULATION_YIELD			2

#define	STRATEGY_MAX_PROGRESS		10000
#define	STRATEGY_MAXF_PROGRESS	10000.

#define	STRATEGY_BASE_YIELD		10000
#define	STRATEGY_BASEF_YIELD		10000.

/***
	策略
*/
class TECH_API CStrategy
{
public:
	CStrategy();
	virtual ~CStrategy();
	//取得策略名称
	static string	GetName( const char* lpszPath );
// Overrides
public:
	//对策略文件的操作,打开,关闭,保存,
	virtual	bool	OpenStrategyFile( const char* lpszPathName, char* lpErr, UINT nMaxSize );
	virtual	bool	SaveStrategyFile( const char* lpszPathName );
//	virtual bool	Serialize(CArchive& ar, LPSTR lpErr, UINT nMaxSize);
	virtual	bool	DoFileSave( );
	virtual	bool	OnClose( );
	virtual	void	OnRealOpViewed( );

protected:
	// 存盘文件路径和名称，不写到策略文件中
	string	m_strPathName;

// Attributes
public:
	void		SetPathName( const char* lpszPathName );
	string		GetPathName( );
	void		SetName(const char*  lpszName );
	string		GetName( );
	void		SetDescript(const char*  lpszDescript );
	string		GetDescript();
	vector<string>	&	GetInstruments( );
	void				SetInstruments( vector<string> & astr );
	void				AddInstrument( const char* lpszCode );
	void				RemoveInstrument( const char* lpszCode );
	string			GetInstrumentTechString( );
	CRateParam		&	GetRateParam( );
	COpParam		&	GetOpParam( );
	CTechParameters	&	GetTechParametersBuy( );
	CTechParameters	&	GetTechParametersSell( );
	CTechParameters	&	GetTechParametersLongTrend( );
	CTechParameters	&	GetTechParametersIndexTrend( );
	vector<DWORD>	&	GetSelectedTechsBuy( );
	vector<DWORD>	&	GetSelectedTechsSell( );
	vector<DWORD>	&	GetSelectedTechsLongTrend( );
	vector<DWORD>	&	GetSelectedTechsIndexTrend( );

// Operations
public:
	// Simulation
	enum	SimuStatus	{
		statusInit		=	0x01,
		statusRunning	=	0x02,
		statusPaused	=	0x03,
		statusFinished	=	0x04,
	};

	// Data Cache
    bool	PrepareData( SIMULATION_CALLBACK fnCallback, void * cookie );
	void	ClearLastIntensity( );
	void	ClearCache( );
	CTechInstrumentContainer &	GetTechInstrumentContainer( );
    bool	CanModifiedNow()	{	return ( SimuIsStatusInit() || SimuIsStatusFinished() );	}

	// Simulation Status
	int		SimuGetCurStatus( )		{	return m_SimuCurrentStatus;	}
	bool	SimuIsStatusInit( )		{	return statusInit == m_SimuCurrentStatus;	}
	bool	SimuIsStatusRunning( )	{	return statusRunning == m_SimuCurrentStatus;	}
	bool	SimuIsStatusPaused( )	{	return statusPaused == m_SimuCurrentStatus;	}
	bool	SimuIsStatusFinished( )	{	return statusFinished == m_SimuCurrentStatus;	}
	void	SimuSetStatusInit( )	{	m_SimuCurrentStatus	=	statusInit;	}
	void	SimuSetStatusRunning( )	{	m_SimuCurrentStatus	=	statusRunning;	}
	void	SimuSetStatusPaused( )	{	m_SimuCurrentStatus	=	statusPaused;	}
	void	SimuSetStatusFinished( ){	m_SimuCurrentStatus	=	statusFinished;	}

	// Simulation
	void	SimuReset( );
	bool	SimuGotoNextTime( );
	time_t	SimuGetCurrentTime( );
	double	SimuGetCurrentCash( );
	bool	SimuOperate( OPRECORD record, bool bTimeStrict = true );
	COpRecordContainer &	SimuGetOpRecord( );
	COpRecordContainer &	SimuGetNextOp( );
	CInstrumentOwnContainer &	SimuGetStockOwn( );
	CAssetSerialContainer &	SimuGetAssetSerial( );
	DWORD	SimuGetCurrentProgress( DWORD dwProgressMax = STRATEGY_MAX_PROGRESS );	//	Not Same as Real
	double	SimuGetAsset(time_t tmCur);
	double	SimuGetCurrentYield( );
	double	SimuGetCurrentYieldIndexPercent( );
	double	SimuGetCurrentYieldPercent( );
	bool	SimuOperateNextop( time_t tmCur, COpRecordContainer & nextop, CTechInstrument & techstock );
	virtual	bool	SimuRun( SIMULATION_CALLBACK fnCallback, void * cookie );

	// Real
	void	RealReset( );
	bool	RealGotoNextTime( );
	time_t	RealGetBeginTime();	//	Not Same as Simu
	time_t	RealGetCurrentTime( );
	double	RealGetCurrentCash( );
	bool	RealOperate( OPRECORD record, bool bTimeStrict = true );
	//bool	RealUnOperate( OPRECORD record );
	COpRecordContainer &	RealGetOpRecord( );
	COpRecordContainer &	RealGetNextOp( );
	CInstrumentOwnContainer &	RealGetStockOwn( );
	CAssetSerialContainer &	RealGetAssetSerial( );
	double	RealGetAsset( time_t tmCur );
	double	RealGetCurrentYield( );
	double	RealGetCurrentYieldIndexPercent( );
	double	RealGetCurrentYieldPercent( );
	bool	RealOperateNextop( time_t tmCur, COpRecordContainer & nextop, CTechInstrument & techstock );
	virtual	bool	RealRun( SIMULATION_CALLBACK fnCallback, void * cookie );
	bool	RealAddOpRecordStrict( OPRECORD record );	//	Not Same as Simu
	bool	RealDeleteOpRecordStrict( size_t nRecord );	//	Not Same as Simu

protected:
	// Properties
	DWORD			m_dwFileVersion;
	string		m_strName;		// 策略名称
	string		m_strDescript;	// 策略说明

	// Stocks
	Plate			m_stocks;		// 策略备选股票

	// Rate
	CRateParam		m_rate;			// 交易费用
	
	// Tech parameters
	CTechParameters	m_paramBuy;			// 买入指标规则
	CTechParameters	m_paramSell;		// 卖出指标规则
	CTechParameters	m_paramLongTrend;	// 长期指标规则
	CTechParameters	m_paramIndexTrend;	// 指数指标规则
	vector<DWORD>	m_anTechsBuy;		// 买入依据的指标
	vector<DWORD>	m_anTechsSell;		// 卖出依据的指标
	vector<DWORD>	m_anTechsLongTrend;	// 长周期趋势依据的指标
	vector<DWORD>	m_anTechsIndexTrend;// 指数趋势依据的指标

	// Operate Parameters
	COpParam		m_opparam;		// 操作规则

	// Simulation
	int				m_SimuCurrentStatus;	// Not Same as Real, 起始，正在进行，暂停，完成
	time_t			m_SimuCurrentTime;		// 模拟当前时间
	double			m_SimuCurrentCash;		// 模拟当前资金
	CInstrumentOwnContainer	m_SimuStockOwn;		// 模拟当前拥有股票
	COpRecordContainer	m_SimuOpRecord;		// 模拟记录
	COpRecordContainer	m_SimuNextOp;		// 模拟下一步操作
	CAssetSerialContainer	m_SimuAssetSerial;	// 模拟资产值序列

	// Real Operate
	time_t			m_RealBeginTime;		//	Not Same as Simu，实战起始时间
	time_t			m_RealCurrentTime;		// 实战当前时间
	double			m_RealCurrentCash;		// 实战当前资金
	CInstrumentOwnContainer	m_RealStockOwn;		// 实战当前拥有股票
	COpRecordContainer	m_RealOpRecord;		// 实战操作记录
	COpRecordContainer	m_RealNextOp;		// 实战下一步操作
	CAssetSerialContainer	m_RealAssetSerial;	// 实战资产值序列

	// Cache Data, Not Saved
	CTechInstrumentContainer	m_techstocks;		// 备选股票，包含信息、数据、技术指标等
};
#endif
